refactor(core): separate Caplet READMEs from runtime config#219
Conversation
Fail persistence closed for invalid or secret-bearing runtime inputs, preserve custom source fingerprints, and keep structured selection hints visible without interpolation. Serialize artifact-lock updates and reconcile interrupted transactions from persisted phases plus observed state.
|
Warning Review limit reached
Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughCaplet Markdown bodies are now operator-facing README content rather than runtime configuration. Runtime fingerprints track declared inputs and semantic configuration, enabling no-op reloads, content-only update statuses, transactional lockfile updates, setup approval gating, and body-free agent-facing projections. ChangesCaplet runtime and README separation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Preview DeployedLanding: https://pr-219.preview.caplets.dev Built from commit 5f6c766 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/cli.ts (1)
3058-3067: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winInstall command doesn't label the new
content_updatedstatus.The
statusunion was widened to include"content_updated"(Line 3048), and theupdatecommand now usesupdateStatusLabel()to surface it distinctly (Lines 4714-4718). But theinstallcommand's remote branch (Lines 3059-3064) and local restore branch (Line 3090) still use the old two-way ternaries (noop/restoredvs"Installed"), so acontent_updatedresult fromrestoreCapletsFromLockfile/remote install falls through to the generic"Installed"/"Restored"label instead of "Content updated", undermining the PR's stated goal of surfacingcontent_updatedduring install.🐛 Proposed fix reusing `updateStatusLabel`-style logic
for (const caplet of result.installed) { - const action = - caplet.status === "noop" - ? "Already installed" - : caplet.status === "restored" - ? "Restored" - : "Installed"; + const action = + caplet.status === "noop" + ? "Already installed" + : caplet.status === "content_updated" + ? "Content updated" + : caplet.status === "restored" + ? "Restored" + : "Installed"; writeOut(`${action} ${caplet.id} to remote ${caplet.destination}\n`); writeCatalogIndexingNotice(caplet.catalogIndexing, writeOut); }for (const caplet of result.installed) { writeOut( - `${caplet.status === "noop" ? "Already installed" : "Restored"} ${caplet.id} to ${localMutationTargetLabel(target, io)}${caplet.destination}\n`, + `${caplet.status === "noop" ? "Already installed" : caplet.status === "content_updated" ? "Content updated" : "Restored"} ${caplet.id} to ${localMutationTargetLabel(target, io)}${caplet.destination}\n`, );Also applies to: 3088-3094
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/cli.ts` around lines 3058 - 3067, Update the install command status-label logic in the remote loop and local restore branch to explicitly handle the “content_updated” status and display “Content updated”. Reuse the existing updateStatusLabel-style helper or equivalent established labeling logic while preserving the current “Already installed”, “Restored”, and “Installed” labels for other statuses.
🧹 Nitpick comments (1)
packages/core/src/cloud/runtime-adapter.ts (1)
84-100: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAvoid recomputing the runtime fingerprint in
runSetup.
runtimeFingerprintForConfig(this.engine.currentConfig())is called insetupPlan(line 84) and again inrunSetup(line 120) for the same caplet. SincerunSetupalready callssetupPlanat line 118, the fingerprint is computed twice. Consider addingpersistenceEligibleto theSetupPlanreturn type sorunSetupcan read it fromplaninstead of recomputing.♻️ Proposed refactor
// In setupPlan return object (around line 101): return { projectFingerprint, capletId, name: caplet.name, contentHash, targetKind, setup: caplet.setup ?? {}, approved, + persistenceEligible: runtimeFingerprint?.persistenceEligible ?? true, commands: caplet.setup?.commands ?? [], verify: caplet.setup?.verify ?? [], }; // In runSetup (around line 119): -const persistenceEligible = - runtimeFingerprintForConfig(this.engine.currentConfig())?.caplets[capletId] - ?.persistenceEligible ?? true; +const persistenceEligible = plan.persistenceEligible;Also applies to: 119-122
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/cloud/runtime-adapter.ts` around lines 84 - 100, Update the SetupPlan return value and setupPlan flow to include the caplet’s persistenceEligible status from the existing runtime fingerprint. In runSetup, reuse that value from the plan returned by setupPlan when determining approval, and remove the second runtimeFingerprintForConfig call while preserving the current approval behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/core/src/cli.ts`:
- Around line 3058-3067: Update the install command status-label logic in the
remote loop and local restore branch to explicitly handle the “content_updated”
status and display “Content updated”. Reuse the existing updateStatusLabel-style
helper or equivalent established labeling logic while preserving the current
“Already installed”, “Restored”, and “Installed” labels for other statuses.
---
Nitpick comments:
In `@packages/core/src/cloud/runtime-adapter.ts`:
- Around line 84-100: Update the SetupPlan return value and setupPlan flow to
include the caplet’s persistenceEligible status from the existing runtime
fingerprint. In runSetup, reuse that value from the plan returned by setupPlan
when determining approval, and remove the second runtimeFingerprintForConfig
call while preserving the current approval behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 5a469b01-6f38-4f53-b3bf-28dfc917f503
📒 Files selected for processing (82)
.changeset/calm-caplet-readme-contract.mdCONCEPTS.mdapps/catalog/src/data/official-catalog.jsonapps/dashboard/src/components/DashboardApp.test.tsxapps/dashboard/src/components/DashboardApp.tsxapps/docs/src/content/docs/reference/caplet-files.mdxapps/docs/src/content/docs/vault.mdxcaplets/ast-grep/CAPLET.mdcaplets/aws/CAPLET.mdcaplets/azure/CAPLET.mdcaplets/browser-use/CAPLET.mdcaplets/cloudflare/CAPLET.mdcaplets/coding-agent-toolkit/CAPLET.mdcaplets/computer-use/CAPLET.mdcaplets/context7/CAPLET.mdcaplets/datadog/CAPLET.mdcaplets/deepwiki/CAPLET.mdcaplets/github/CAPLET.mdcaplets/gmail/CAPLET.mdcaplets/google-chat/CAPLET.mdcaplets/google-docs/CAPLET.mdcaplets/google-drive/CAPLET.mdcaplets/google-forms/CAPLET.mdcaplets/google-meet/CAPLET.mdcaplets/google-sheets/CAPLET.mdcaplets/google-slides/CAPLET.mdcaplets/google-tasks/CAPLET.mdcaplets/google-workspace/CAPLET.mdcaplets/linear/CAPLET.mdcaplets/lsp/CAPLET.mdcaplets/mongodb/CAPLET.mdcaplets/neon/CAPLET.mdcaplets/notion/CAPLET.mdcaplets/npm/CAPLET.mdcaplets/osv/CAPLET.mdcaplets/pagerduty/CAPLET.mdcaplets/playwright/CAPLET.mdcaplets/posthog/CAPLET.mdcaplets/pypi/CAPLET.mdcaplets/repo-cli/CAPLET.mdcaplets/sentry/CAPLET.mdcaplets/sourcegraph/CAPLET.mdcaplets/stripe/CAPLET.mdcaplets/supabase/CAPLET.mdcaplets/terraform/CAPLET.mdcaplets/vercel/CAPLET.mddocs/plans/2026-07-13-001-refactor-caplet-operator-readme-separation-plan.mdpackages/core/src/caplet-files-bundle.tspackages/core/src/caplet-source/bundle.tspackages/core/src/caplet-source/filesystem.tspackages/core/src/caplet-source/index.tspackages/core/src/caplet-source/parse.tspackages/core/src/caplet-source/runtime-fingerprint.tspackages/core/src/caplet-source/types.tspackages/core/src/cli.tspackages/core/src/cli/author.tspackages/core/src/cli/install.tspackages/core/src/cli/lockfile.tspackages/core/src/cli/setup-caplet.tspackages/core/src/cloud/runtime-adapter.tspackages/core/src/code-mode/declarations.tspackages/core/src/config-runtime.tspackages/core/src/config.tspackages/core/src/current-host/catalog-operations.tspackages/core/src/current-host/catalog.tspackages/core/src/engine.tspackages/core/src/index.tspackages/core/src/setup/hash.tspackages/core/test/backend-operation-dispatch.test.tspackages/core/test/caplet-files.test.tspackages/core/test/caplet-source.test.tspackages/core/test/caplets-lockfile.test.tspackages/core/test/cli.test.tspackages/core/test/code-mode-declarations.test.tspackages/core/test/config.test.tspackages/core/test/current-host-catalog-operations.test.tspackages/core/test/engine.test.tspackages/core/test/native.test.tspackages/core/test/runtime-fingerprint.test.tspackages/core/test/serve-http.test.tspackages/core/test/setup-runner.test.tsscripts/generate-docs-reference.ts
|
| Filename | Overview |
|---|---|
| packages/core/src/cli/install.ts | Major refactor introducing staged-transaction installs with journal-based crash recovery, advisory lock with dead-PID recovery, and a new content_updated status for README-only upstream changes. One gap: installCapletsUnlocked doesn't run recoverInterruptedCapletTransactions, so a journal left by an interrupted restore/update for the same caplet ID could be orphaned by a subsequent install and block future restore/update. |
| packages/core/src/caplet-source/runtime-fingerprint.ts | New module producing domain-separated SHA-256 fingerprints over normalized frontmatter, declared inputs, provenance, and host settings. Path normalization, cycle detection, and secret-path exclusions are all handled. |
| packages/core/src/cli/lockfile.ts | Adds CapletsLockRuntimeFingerprint field to lock entries and splits writeCapletsLockfile into writeCapletsLockfileTemporary + replaceCapletsLockfileTemporary to support the two-phase commit protocol. runtimeFingerprint is persisted but currently unused for the content_updated comparison. |
| packages/core/src/caplet-source/parse.ts | Integrates runtime fingerprinting into parse: declared input existence is now determined from the fingerprint snapshot rather than direct file reads, and runtimeFingerprint is included in the parse result for downstream consumers. |
| packages/core/src/engine.ts | Adds fingerprint-based reload no-op detection: if both hostConfigurationFingerprint and resolvedExecutionFingerprint are unchanged, the reload returns early without rebuilding registries or backend clients. |
| packages/core/src/config.ts | Removes useWhen/avoidWhen fields and the body field from all Caplet config types and Zod schemas. Adds runtimeFingerprintForConfig with WeakMap caching. |
| packages/core/src/current-host/catalog-operations.ts | Wraps indexInstalledCapletsFromLockfile in a try/catch so catalog indexing failures no longer propagate and block a completed install/update. |
| apps/dashboard/src/components/DashboardApp.tsx | Adds status-aware UI messaging for the new content_updated and restored statuses. Clean extension of the existing message pattern. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant U as User
participant IT as installCaplets / restoreCaplets / updateCaplets
participant TL as withLockfileTransaction
participant RT as recoverInterruptedTxns
participant SA as stageAndValidateCandidate
participant CS as commitStagedCapletAndLock
participant LF as Lockfile
U->>IT: restore / update (lockfilePath)
IT->>TL: acquire .transaction.lock (O_EXCL)
TL->>RT: recoverInterruptedCapletTransactions
RT->>LF: "read journals (.caplet-txn-*.json)"
RT->>LF: advance / revert lock as needed
TL->>SA: copyInstallPath to staged artifact
SA->>SA: fingerprintArtifact (runtime snapshot)
SA->>SA: hashInstalledArtifact
SA-->>TL: CandidateArtifact
TL->>CS: write journal phases (prepared through lock_replaced)
CS->>LF: writeLockfileTemporary + replaceLockfileTemporary
CS->>CS: cleanupTransactionPaths (remove journal)
TL->>TL: release .transaction.lock
IT-->>U: installed[] with status (noop / restored / content_updated / updated)
Note over U,IT: installCaplets (fresh install) skips recoverInterruptedTxns — stale journals for the same caplet ID are not cleaned up
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant U as User
participant IT as installCaplets / restoreCaplets / updateCaplets
participant TL as withLockfileTransaction
participant RT as recoverInterruptedTxns
participant SA as stageAndValidateCandidate
participant CS as commitStagedCapletAndLock
participant LF as Lockfile
U->>IT: restore / update (lockfilePath)
IT->>TL: acquire .transaction.lock (O_EXCL)
TL->>RT: recoverInterruptedCapletTransactions
RT->>LF: "read journals (.caplet-txn-*.json)"
RT->>LF: advance / revert lock as needed
TL->>SA: copyInstallPath to staged artifact
SA->>SA: fingerprintArtifact (runtime snapshot)
SA->>SA: hashInstalledArtifact
SA-->>TL: CandidateArtifact
TL->>CS: write journal phases (prepared through lock_replaced)
CS->>LF: writeLockfileTemporary + replaceLockfileTemporary
CS->>CS: cleanupTransactionPaths (remove journal)
TL->>TL: release .transaction.lock
IT-->>U: installed[] with status (noop / restored / content_updated / updated)
Note over U,IT: installCaplets (fresh install) skips recoverInterruptedTxns — stale journals for the same caplet ID are not cleaned up
Reviews (4): Last reviewed commit: "fix(core): preserve lock identity during..." | Re-trigger Greptile
Recover dead-owner transaction locks without weakening live-writer exclusion, keep staging and commit on one transaction path set, and expose content-only install statuses consistently. Document literal selection-hint migration and reuse hosted setup fingerprint eligibility.
Addressed: both remote install and local lockfile-restore human output now render
Addressed: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/core/src/cli/install.ts (1)
448-560: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftSignificant duplication between
restoreCapletsFromLockfileUnlockedandupdateCapletsFromLockfileUnlocked.Both functions (this range and Lines 343-428) repeat the same stage → prospective-entry → lock-changed detection → noop/commit branching → result-push → finally-cleanup skeleton, differing only in status derivation (
restoredvsnoop/content_updated/updated) and a couple of update-specific checks (locked-source availability, risk gating). This duplication risks the two paths silently diverging on future fixes (e.g., a bug fix to the staged-cleanup or candidate-lifecycle handling applied to one but not the other).Consider extracting the shared staging/commit/result-assembly flow into a helper parameterized by a status-resolution callback.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/cli/install.ts` around lines 448 - 560, Extract the shared stage, prospective-entry, lock-change, status branching, commit, result assembly, and staged-candidate cleanup flow from restoreCapletsFromLockfileUnlocked and updateCapletsFromLockfileUnlocked into a helper. Parameterize it with the status-resolution callback and preserve each caller’s unique source validation, risk gating, and restored versus update status behavior; then have both functions use the helper to keep candidate lifecycle handling consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/core/src/cli/install.ts`:
- Around line 448-560: Extract the shared stage, prospective-entry, lock-change,
status branching, commit, result assembly, and staged-candidate cleanup flow
from restoreCapletsFromLockfileUnlocked and updateCapletsFromLockfileUnlocked
into a helper. Parameterize it with the status-resolution callback and preserve
each caller’s unique source validation, risk gating, and restored versus update
status behavior; then have both functions use the helper to keep candidate
lifecycle handling consistent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: fde6b67b-154f-4284-8b29-16f56fd030c7
⛔ Files ignored due to path filters (1)
packages/core/src/code-mode/runtime-api.generated.tsis excluded by!**/*.generated.*
📒 Files selected for processing (84)
.changeset/calm-caplet-readme-contract.mdapps/catalog/src/data/official-catalog.jsonapps/catalog/src/lib/ingest.tsapps/catalog/test/ingest.test.tsapps/docs/src/content/docs/reference/caplet-files.mdxapps/docs/src/content/docs/reference/code-mode-api.mdxapps/docs/src/content/docs/reference/config.mdxapps/docs/src/content/docs/vault.mdxapps/landing/public/caplet.schema.jsonapps/landing/public/config.schema.jsoncaplets/ast-grep/CAPLET.mdcaplets/aws/CAPLET.mdcaplets/azure/CAPLET.mdcaplets/browser-use/CAPLET.mdcaplets/cloudflare/CAPLET.mdcaplets/coding-agent-toolkit/CAPLET.mdcaplets/computer-use/CAPLET.mdcaplets/context7/CAPLET.mdcaplets/datadog/CAPLET.mdcaplets/deepwiki/CAPLET.mdcaplets/github/CAPLET.mdcaplets/gmail/CAPLET.mdcaplets/google-chat/CAPLET.mdcaplets/google-docs/CAPLET.mdcaplets/google-drive/CAPLET.mdcaplets/google-meet/CAPLET.mdcaplets/google-sheets/CAPLET.mdcaplets/google-slides/CAPLET.mdcaplets/google-tasks/CAPLET.mdcaplets/google-workspace/CAPLET.mdcaplets/lsp/CAPLET.mdcaplets/mongodb/CAPLET.mdcaplets/neon/CAPLET.mdcaplets/notion/CAPLET.mdcaplets/npm/CAPLET.mdcaplets/osv/CAPLET.mdcaplets/pagerduty/CAPLET.mdcaplets/playwright/CAPLET.mdcaplets/pypi/CAPLET.mdcaplets/sourcegraph/CAPLET.mdcaplets/stripe/CAPLET.mdcaplets/supabase/CAPLET.mdcaplets/terraform/CAPLET.mdcaplets/vercel/CAPLET.mddocs/plans/2026-07-13-001-refactor-caplet-operator-readme-separation-plan.mdpackages/core/src/attach/api.tspackages/core/src/capability-description.tspackages/core/src/caplet-files-bundle.tspackages/core/src/catalog/entry.tspackages/core/src/catalog/types.tspackages/core/src/cli-tools.tspackages/core/src/cli.tspackages/core/src/cli/code-mode.tspackages/core/src/cli/install.tspackages/core/src/cloud/runtime-adapter.tspackages/core/src/code-mode/declarations.tspackages/core/src/code-mode/runtime-api.d.tspackages/core/src/code-mode/types.tspackages/core/src/config-runtime.tspackages/core/src/config.tspackages/core/src/current-host/catalog.tspackages/core/src/exposure/projection.tspackages/core/src/graphql.tspackages/core/src/http-actions.tspackages/core/src/native/remote.tspackages/core/src/native/service.tspackages/core/src/registry.tspackages/core/src/serve/session.tspackages/core/src/setup/types.tspackages/core/test/attach-api.test.tspackages/core/test/catalog-model.test.tspackages/core/test/cli-install-output.test.tspackages/core/test/cli-remote.test.tspackages/core/test/cli.test.tspackages/core/test/code-mode-declarations.test.tspackages/core/test/config.test.tspackages/core/test/native-remote.test.tspackages/core/test/native.test.tspackages/core/test/registry.test.tspackages/core/test/runtime-fingerprint.test.tsschemas/caplet.schema.jsonschemas/caplets-config.schema.jsonscripts/generate-catalog-index.tsscripts/generate-docs-reference.ts
💤 Files with no reviewable changes (61)
- packages/core/src/capability-description.ts
- apps/docs/src/content/docs/reference/code-mode-api.mdx
- packages/core/src/code-mode/types.ts
- packages/core/src/catalog/entry.ts
- caplets/browser-use/CAPLET.md
- caplets/google-meet/CAPLET.md
- caplets/google-chat/CAPLET.md
- caplets/coding-agent-toolkit/CAPLET.md
- caplets/ast-grep/CAPLET.md
- packages/core/src/cli/code-mode.ts
- caplets/context7/CAPLET.md
- caplets/computer-use/CAPLET.md
- packages/core/src/http-actions.ts
- caplets/playwright/CAPLET.md
- caplets/google-docs/CAPLET.md
- packages/core/src/catalog/types.ts
- caplets/google-slides/CAPLET.md
- caplets/azure/CAPLET.md
- packages/core/src/cli-tools.ts
- caplets/gmail/CAPLET.md
- apps/catalog/src/lib/ingest.ts
- apps/docs/src/content/docs/reference/config.mdx
- caplets/datadog/CAPLET.md
- caplets/vercel/CAPLET.md
- caplets/github/CAPLET.md
- packages/core/src/serve/session.ts
- caplets/npm/CAPLET.md
- caplets/osv/CAPLET.md
- caplets/lsp/CAPLET.md
- caplets/terraform/CAPLET.md
- caplets/google-workspace/CAPLET.md
- caplets/sourcegraph/CAPLET.md
- caplets/google-drive/CAPLET.md
- caplets/supabase/CAPLET.md
- packages/core/src/registry.ts
- packages/core/test/native-remote.test.ts
- caplets/cloudflare/CAPLET.md
- scripts/generate-catalog-index.ts
- caplets/pypi/CAPLET.md
- caplets/stripe/CAPLET.md
- packages/core/src/code-mode/runtime-api.d.ts
- caplets/deepwiki/CAPLET.md
- packages/core/src/graphql.ts
- packages/core/src/native/service.ts
- apps/catalog/test/ingest.test.ts
- packages/core/test/registry.test.ts
- caplets/notion/CAPLET.md
- caplets/aws/CAPLET.md
- caplets/mongodb/CAPLET.md
- packages/core/test/attach-api.test.ts
- caplets/pagerduty/CAPLET.md
- caplets/google-tasks/CAPLET.md
- caplets/neon/CAPLET.md
- caplets/google-sheets/CAPLET.md
- apps/landing/public/config.schema.json
- schemas/caplets-config.schema.json
- apps/landing/public/caplet.schema.json
- schemas/caplet.schema.json
- packages/core/test/native.test.ts
- packages/core/src/current-host/catalog.ts
- packages/core/src/caplet-files-bundle.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- .changeset/calm-caplet-readme-contract.md
- apps/docs/src/content/docs/vault.mdx
- packages/core/src/cli.ts
- packages/core/src/cloud/runtime-adapter.ts
- docs/plans/2026-07-13-001-refactor-caplet-operator-readme-separation-plan.md
- packages/core/test/runtime-fingerprint.test.ts
Addressed: installed-artifact fingerprinting is now best-effort and falls back to |
Addressed: extracted the shared candidate finalization seam into |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/core/src/cli/install.ts`:
- Around line 379-390: Validate the staged candidate’s artifact hash against
entry.installedHash in the restore path before calling finalizeStagedCandidate.
Reject the restore when they differ, preserving the existing locked entry and
preventing prospective from replacing its hash; only the update flow may advance
the lock entry.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: dcf0c53d-3140-4fec-b0df-036a092644f1
📒 Files selected for processing (2)
packages/core/src/cli/install.tspackages/core/test/cli.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/core/test/cli.test.ts
Summary
Caplet authors can now use the Markdown body as a real operator README without accidentally changing agent behavior, runtime identity, setup approval, or backend reloads. YAML frontmatter is the sole runtime authority; explicitly referenced bundle assets remain runtime inputs, while README prose has an independent content lifecycle.
Design decisions
descriptionremains the concise Caplet-level capability description. The redundantuseWhenandavoidWhenfields are removed from Caplet and configured-action schemas, projections, generated references, catalog metadata, and the official corpus; downstream tools may still expose backend-owned selection hints.content_updatedwithout setup churn. Artifact and lockfile commits are serialized per lockfile and recover from persisted transaction phases plus observed artifact/lock state.This also establishes a storage-independent contract for a future SQL-backed configuration store: structured runtime fields and operator documentation are separate projections even when they share one portable
CAPLET.mdartifact today.Validation
pnpm verifySummary by CodeRabbit
useWhen/avoidWhenconfiguration fields.